; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s

define void @phi_feeding_phi_args(i8 %a, i8 %b) {
; CHECK-LABEL: phi_feeding_phi_args:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    and w8, w0, #0xff
; CHECK-NEXT:    and w9, w1, #0xff
; CHECK-NEXT:    cmp w8, w9
; CHECK-NEXT:    csel w8, w8, w9, hi
; CHECK-NEXT:  .LBB0_1: // %loop
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    sub w9, w8, #2
; CHECK-NEXT:    lsl w10, w8, #1
; CHECK-NEXT:    cmp w8, #254
; CHECK-NEXT:    csel w8, w9, w10, lo
; CHECK-NEXT:    cmp w8, #255
; CHECK-NEXT:    b.ne .LBB0_1
; CHECK-NEXT:  // %bb.2: // %exit
; CHECK-NEXT:    ret
entry:
  %0 = icmp ugt i8 %a, %b
  br i1 %0, label %preheader, label %empty

empty:                                            ; preds = %entry
  br label %preheader

preheader:                                        ; preds = %empty, %entry
  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
  br label %loop

loop:                                             ; preds = %if.end, %preheader
  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
  %cmp = icmp ult i8 %val, -2
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %loop
  %inc = sub nuw i8 %val, 2
  br label %if.end

if.else:                                          ; preds = %loop
  %inc1 = shl nuw i8 %val, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %inc2 = phi i8 [ %inc, %if.then ], [ %inc1, %if.else ]
  %cmp1 = icmp eq i8 %inc2, -1
  br i1 %cmp1, label %exit, label %loop

exit:                                             ; preds = %if.end
  ret void
}

define void @phi_feeding_phi_zeroext_args(i8 zeroext %a, i8 zeroext %b) {
; CHECK-LABEL: phi_feeding_phi_zeroext_args:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    cmp w0, w1
; CHECK-NEXT:    csel w8, w0, w1, hi
; CHECK-NEXT:  .LBB1_1: // %loop
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    sub w9, w8, #2
; CHECK-NEXT:    lsl w10, w8, #1
; CHECK-NEXT:    cmp w8, #254
; CHECK-NEXT:    csel w8, w9, w10, lo
; CHECK-NEXT:    cmp w8, #255
; CHECK-NEXT:    b.ne .LBB1_1
; CHECK-NEXT:  // %bb.2: // %exit
; CHECK-NEXT:    ret
entry:
  %0 = icmp ugt i8 %a, %b
  br i1 %0, label %preheader, label %empty

empty:                                            ; preds = %entry
  br label %preheader

preheader:                                        ; preds = %empty, %entry
  %1 = phi i8 [ %a, %entry ], [ %b, %empty ]
  br label %loop

loop:                                             ; preds = %if.end, %preheader
  %val = phi i8 [ %1, %preheader ], [ %inc2, %if.end ]
  %cmp = icmp ult i8 %val, -2
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %loop
  %inc = sub nuw i8 %val, 2
  br label %if.end

if.else:                                          ; preds = %loop
  %inc1 = shl nuw i8 %val, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %inc2 = phi i8 [ %inc, %if.then ], [ %inc1, %if.else ]
  %cmp1 = icmp eq i8 %inc2, -1
  br i1 %cmp1, label %exit, label %loop

exit:                                             ; preds = %if.end
  ret void
}

define void @phi_i16() {
; CHECK-LABEL: phi_i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    mov w8, wzr
; CHECK-NEXT:    mov w9, #1
; CHECK-NEXT:  .LBB2_1: // %loop
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w8, #128
; CHECK-NEXT:    cinc w10, w9, lo
; CHECK-NEXT:    add w8, w8, w10
; CHECK-NEXT:    cmp w8, #253
; CHECK-NEXT:    b.lo .LBB2_1
; CHECK-NEXT:  // %bb.2: // %exit
; CHECK-NEXT:    ret
entry:
  br label %loop

loop:                                             ; preds = %if.end, %entry
  %val = phi i16 [ 0, %entry ], [ %inc2, %if.end ]
  %cmp = icmp ult i16 %val, 128
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %loop
  %inc = add nuw i16 %val, 2
  br label %if.end

if.else:                                          ; preds = %loop
  %inc1 = add nuw i16 %val, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %inc2 = phi i16 [ %inc, %if.then ], [ %inc1, %if.else ]
  %cmp1 = icmp ult i16 %inc2, 253
  br i1 %cmp1, label %loop, label %exit

exit:                                             ; preds = %if.end
  ret void
}

define i8 @ret_i8() {
; CHECK-LABEL: ret_i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    mov w0, wzr
; CHECK-NEXT:    mov w8, #1
; CHECK-NEXT:  .LBB3_1: // %loop
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w0, #128
; CHECK-NEXT:    cinc w9, w8, lo
; CHECK-NEXT:    add w0, w0, w9
; CHECK-NEXT:    cmp w0, #252
; CHECK-NEXT:    b.hi .LBB3_1
; CHECK-NEXT:  // %bb.2: // %exit
; CHECK-NEXT:    ret
entry:
  br label %loop

loop:                                             ; preds = %if.end, %entry
  %val = phi i8 [ 0, %entry ], [ %inc2, %if.end ]
  %cmp = icmp ult i8 %val, -128
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %loop
  %inc = add nuw i8 %val, 2
  br label %if.end

if.else:                                          ; preds = %loop
  %inc1 = add nuw i8 %val, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %inc2 = phi i8 [ %inc, %if.then ], [ %inc1, %if.else ]
  %cmp1 = icmp ult i8 %inc2, -3
  br i1 %cmp1, label %exit, label %loop

exit:                                             ; preds = %if.end
  ret i8 %inc2
}

define i16 @phi_multiple_undefs(i16 zeroext %arg) {
; CHECK-LABEL: phi_multiple_undefs:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    mov w8, wzr
; CHECK-NEXT:    mov w9, #1
; CHECK-NEXT:  .LBB4_1: // %loop
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w8, #128
; CHECK-NEXT:    cinc w10, w9, lo
; CHECK-NEXT:    add w8, w8, w10
; CHECK-NEXT:    cmp w8, #253
; CHECK-NEXT:    b.lo .LBB4_1
; CHECK-NEXT:  // %bb.2: // %exit
; CHECK-NEXT:    ret
entry:
  br label %loop

loop:                                             ; preds = %if.end, %entry
  %val = phi i16 [ undef, %entry ], [ %inc2, %if.end ]
  %cmp = icmp ult i16 %val, 128
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %loop
  %inc = add nuw i16 %val, 2
  br label %if.end

if.else:                                          ; preds = %loop
  %inc1 = add nuw i16 %val, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %inc2 = phi i16 [ %inc, %if.then ], [ %inc1, %if.else ]
  %unrelated = phi i16 [ undef, %if.then ], [ %arg, %if.else ]
  %cmp1 = icmp ult i16 %inc2, 253
  br i1 %cmp1, label %loop, label %exit

exit:                                             ; preds = %if.end
  ret i16 %unrelated
}

define i16 @promote_arg_return(i16 zeroext %arg1, i16 zeroext %arg2, ptr %res) {
; CHECK-LABEL: promote_arg_return:
; CHECK:       // %bb.0:
; CHECK-NEXT:    add w8, w0, w0, lsl #1
; CHECK-NEXT:    add w8, w8, #45
; CHECK-NEXT:    cmp w8, w1
; CHECK-NEXT:    cset w8, lo
; CHECK-NEXT:    strb w8, [x2]
; CHECK-NEXT:    ret
  %add = add nuw i16 %arg1, 15
  %mul = mul nuw nsw i16 %add, 3
  %cmp = icmp ult i16 %mul, %arg2
  %conv = zext i1 %cmp to i8
  store i8 %conv, ptr %res, align 1
  ret i16 %arg1
}

define i16 @signext_bitcast_phi_select(i16 signext %start, ptr %in) {
; CHECK-LABEL: signext_bitcast_phi_select:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    and w8, w0, #0xffff
; CHECK-NEXT:    mov w9, #-1
; CHECK-NEXT:    cmp w9, w8, sxth
; CHECK-NEXT:    b.lt .LBB6_3
; CHECK-NEXT:  .LBB6_1: // %if.then
; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ldrh w0, [x1, w8, sxtw #1]
; CHECK-NEXT:    cmp w0, w8
; CHECK-NEXT:    b.eq .LBB6_4
; CHECK-NEXT:  // %bb.2: // %if.else
; CHECK-NEXT:    // in Loop: Header=BB6_1 Depth=1
; CHECK-NEXT:    lsr w10, w8, #15
; CHECK-NEXT:    eor w10, w10, #0x1
; CHECK-NEXT:    add w8, w10, w8
; CHECK-NEXT:    cmp w9, w8, sxth
; CHECK-NEXT:    b.ge .LBB6_1
; CHECK-NEXT:  .LBB6_3:
; CHECK-NEXT:    mov w0, wzr
; CHECK-NEXT:  .LBB6_4: // %exit
; CHECK-NEXT:    ret
entry:
  %const = bitcast i16 -1 to i16
  br label %for.body

for.body:                                         ; preds = %if.else, %entry
  %idx = phi i16 [ %select, %if.else ], [ %start, %entry ]
  %cmp.i = icmp sgt i16 %idx, %const
  br i1 %cmp.i, label %exit, label %if.then

if.then:                                          ; preds = %for.body
  %idx.next = getelementptr i16, ptr %in, i16 %idx
  %ld = load i16, ptr %idx.next, align 2
  %cmp1.i = icmp eq i16 %ld, %idx
  br i1 %cmp1.i, label %exit, label %if.else

if.else:                                          ; preds = %if.then
  %lobit = lshr i16 %idx, 15
  %lobit.not = xor i16 %lobit, 1
  %select = add nuw i16 %lobit.not, %idx
  br label %for.body

exit:                                             ; preds = %if.then, %for.body
  %res = phi i16 [ %ld, %if.then ], [ 0, %for.body ]
  ret i16 %res
}
